﻿@using Resource;
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
    <meta http-equiv="Expires" content="0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache" content="no-cache">
    @{
        await Html.RenderPartialAsync("/Views/Shared/_LayoutScript.cshtml");
    }
    @{
        await Html.RenderPartialAsync("/Views/Shared/_StyleCss.cshtml");
    }
    <script src="/lib/xlsx/xlsx.full.min.js?v=@DateTime.Now.Ticks"></script>
    <link href="/css/YieldFailureMode.css?v=@DateTime.Now.Ticks" rel="stylesheet" />
    <title>YieldFailureMode</title>
    <style type="text/css">
        /*报表样式*/
        html, body {
            background: url(../images/ProcessCapacity/bgwhite.png) no-repeat;
            background-size: cover;
            font-size: .16rem;
            color: #ffffff;
            position: relative;
            width: 100%;
            height: 100%;
            font-family: myFirstFont !important;
            color: black;
        }

        .hover-image {
            display: none;
            position: absolute;
            top: 20px;
            left: 0;
            width: 35vw;
            border: 1px solid #ccc;
            background: #fff;
            z-index: 999;
        }

        .warn-flag:hover .hover-image {
            display: block;
        }

        /*报表放大*/
        #maximizedreport {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            margin: 0;
            z-index: 1000;
            transition: all 0.3s;
            font-size: 1.5em !important;
            background-color: #f5f5f5;
        }

        #maximizedreport .note {
            font-size: 0.85em !important;
        }

        #maximizedreport #Tab1 {
            height: 90vh;
        }

        #maximizedreport #board #startdate,
        #maximizedreport #board #enddate {
            font-size: 0.85em !important;
            width: 12.5vw;
        }

        #maximizedreport #board select,
        #maximizedreport #board button,
        #maximizedreport #board .titleinput,
        #maximizedreport #dateto select
        #maximizedreport #dateno select {
            font-size: 0.85em !important;
            width: 9vw;
        }

        #maximizedreport #chart-container {
            height: 90vh;
            font-size: 0.85em !important;
        }

        #maximizedreport #chart-container th {
            font-size: 1.45em !important;
        }

        #maximizedreport .popup {
            width: 80%;
        }

        #maximizedreport .popup span,
        #maximizedreport #report td {
            font-size: 0.85em !important;
        }

        #maximizedreport #report th {
            font-size: 1.5em !important;
        }

        .rightTop {
            background-color: #f7fdff;
        }

        .dropbtn, button {
            background-color: #0aa9cd;
        }

        #query > button {
            background-color: #0aa9cd;
            border: 2px solid #0aa9cd;
        }

        .dropdown-content {
            background-color: #12bed0;
        }

        .Zebra {
            background-color: #e5ecff;
        }

        .ZebraNo {
            background-color: #e8f1f9;
        }

        .ZebraTo {
            background-color: #ffffff;
        }

        .warn {
            background-color: #ffcccc;
        }

        .note {
            color: red;
            font-size: 0.15rem;
            font-weight: bolder;
        }

        .warning {
            background-color: #ffaf0078;
            border-color: transparent;
        }

        .danger {
            background-color: #ff1f0078;
            border-color: transparent;
        }

        .jobnum:hover {
            background-color: #b3f1fe;
        }

        .truncate {
            /* max-width: 1.2rem; */
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            border-color: transparent;
        }

        td.percentage {
            border-color: transparent;
        }
        /*END*/

        #Tab1 {
            /* border: 1px solid #59ebe8; */
            height: 9.6rem;
            background-image: url('../images/loading.gif');
            background-size: 0.8rem 0.8rem;
            background-repeat: no-repeat;
            background-position: center;
        }

        .popup {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 80%;
            background-color: white;
            box-shadow: 0 0 10px rgba(4, 193, 250,1);
            border-radius: 8px;
            z-index: 7;
        }

        #yield_tbody {
            border-collapse: collapse;
        }

        #yield_tbody tr,
        #yield_tbody td {
            border: 1px solid gray;
        }

        .switch-container {
            display: flex;
            align-items: center;
        }

        .switch {
            position: relative;
            display: inline-block;
            width: 0.42rem;
            height: 0.24rem;
            top: 0.1rem;
        }

        .switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }

        .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #ccc;
            transition: 0.4s;
            border-radius: 0.5rem;
        }

        .slider:before {
            position: absolute;
            content: "";
            height: 0.18rem;
            width: 0.18rem;
            left: 0.03rem;
            bottom: 0.028rem;
            background-color: white;
            transition: 0.4s;
            border-radius: 50%;
        }

        input:checked + .slider {
            background-color: #4caf50;
        }

        input:checked + .slider:before {
            transform: translateX(0.18rem);
        }
    </style>
</head>
<body class="fill-parent" style="overflow-y: hidden; color: black;">
    <div class="main">
        <div class="header">
            <div class="header-left fl">
                <img src="/images/logo.png?v=@DateTime.Now.Ticks" class="scaled-image" draggable="false" oncontextmenu="return false;" ondragstart="return false;" />
            </div>
            <div class="btn">
                <spn>
                    <div id="query">
                        <div class="dropdown">
                            <button class="dropbtn">@Label.Desktop</button>
                            <div class="dropdown-content">
                                <a class="menudropdown" href=@Html.Raw($"https://dashboard.li.lumentuminc.net/API/DesktopApp/Dashboard.exe?v={DateTime.Now.Ticks}") download>@Label.Local</a>
                                <a class="menudropdown" href=@Html.Raw($"https://dashboard.li.lumentuminc.net/API/DesktopApp/Dashboard_lnk.zip?v={DateTime.Now.Ticks}") download>@Label.Shortcut</a>
                            </div>
                        </div>
                        <div class="dropdown">
                            <button class="dropbtn">@Label.Data@Label.Datum</button>
                            <div class="dropdown-content">
                                <a class="menudropdown" onclick="exportDdata('FailureMode')">@Label.Data@Label.Export</a>
                            </div>
                        </div>
                        <div class="dropdown">
                            <button class="dropbtn">@Label.Language</button>
                            <div class="dropdown-content">
                                <a class="menudropdown" onclick="setLanguageCookie('@Const.CNLANGUAGE')">@Label.Chinese</a>
                                <a class="menudropdown" onclick="setLanguageCookie('@Const.USLANGUAGE')">@Label.English</a>
                            </div>
                        </div>
                        <button class="modalBtn dimension">@Label.Full</button>
                    </div>
                </spn>
            </div>
            <div class="header-center fl">
                <div class="header-title"></div>
                <div class="header-img"></div>
            </div>
            <div class="header-right fl" id="time"></div>
            <div class="header-bottom fl"></div>
        </div>
        <div class="center">
            <div class="center-left fl">
                <div class="left-top rightTop border" id="report_id" ondblclick="maximizedreport()">
                    <div class="title note">
                        <span class="warn-flag" style="color:red; position: relative;">ℹ️<img src="../images/lot.png?v=@DateTime.Now.Ticks" class="hover-image" /></span>
                        @Html.Raw(Label.Note_YieldByFailureMode)
                    </div>
                    <div id="board" class="chart">
                        <div class="query">
                            <span class="titleinput tle">@Html.Raw(Label.Product):</span>
                            <select id="cmb_product_code" placeholder="select ProductCode"></select>
                            <span class="titleinput tle">@Html.Raw(Label.Process):</span>
                            <select id="cmb_process" placeholder="select Process" style="width: 1.9rem;">
                                <option value="ALL">ALL</option>
                            </select>
                            <span class="titleinput tle">Type:</span>
                            <select id="cmb_type" placeholder="select Type">
                                <option value="Daily">Daily</option>
                                <option value="Weekly">Weekly</option>
                                <option value="Monthly">Monthly</option>
                                <option value="Yearly">Yearly</option>
                                <option value="CQ">Quarterly(CQ)</option>
                                <option value="FQ">Quarterly(FQ)</option>
                            </select>
                             @* DAY *@
                            <span id="dateno">
                                <span class="titleinput tle">@Label.Time:</span>
                                <input type="date" id="startdate" name="startdate" placeholder="@Label.Start@Label.Time">
                                <span class="titleinput tle">@Label.To</span>
                                <input type="date" id="enddate" name="enddate" placeholder="@Label.Start@Label.End" style="margin-right: 0.1rem;">
                            </span>
                            @* WEEK\MONTH\YEAR\CQ\FQ *@
                            <span id="dateto">
                                <span class="titleinput tle">@Label.Time:</span>
                                <select id="startyear" placeholder="select date"></select>
                                <select id="startto"></select>
                                <span class="titleinput tle">@Label.To</span>
                                <select id="endyear" placeholder="select date"></select>
                                <select id="endto"></select>
                            </span>
                            <button id="btn_query" class="btn btn-primary  btn-sm col-md-12" type="button" onclick="Getdata()">@Label.Query</button>
                            <div style="float: right; line-height:0.5rem;">
                                <button id="btn_detail" class="btn btn-primary  btn-sm col-md-12" type="button" onclick="reportDetail()">@Label.Data@Label.Detail</button>
                            </div>
                        </div>
                        <div id="Tab1">
                            <div id="chart-container">
                                <div id="etoe-chart"></div>
                                <div id="fpy-chart"></div>
                            </div>
                            <div class="popup">
                                <span class="report_close" style="font-size:0.18rem;color:red; float:right;font-weight:bold;" onclick="funclose()">关闭×</span>
                                <div style="height:0.3rem">
                                    <span class="popup-title" style="font-size:0.15rem;color:#007bff;font-weight:bold;line-height:0.3rem;padding-left: 0.15rem;"></span>
                                </div>
                                <div id="report"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script type="text/javascript" href="?v=@DateTime.Now.Ticks">
        $(".popup").css("display", "none");
        $(document).ready(function () {
            var whei = $(window).height();
            $("html").css({ fontSize: whei / 12.5 });
            $(window).resize(function () {
                if ($(".dimension").text() == "@Html.Raw(Label.Full)") {
                    var whei = $(window).height();
                    $("html").css({ fontSize: whei / 12.5 });
                }
                else {
                    var whei = $(window).width();
                    $("html").css({ fontSize: whei / 22 })
                }
            });

            function numberToUpperCase(number) {
                var uppercaseMonths = [
                    '一月', '二月', '三月', '四月', '五月', '六月',
                    '七月', '八月', '九月', '十月', '十一月', '十二月'
                ];
                return uppercaseMonths[number - 1];
            }
            var myDate = new Date();
            var result = numberToUpperCase(myDate.getMonth() + 1);
            $('.header-title').html("@Html.Raw(Label.Board_YieldByFailureMode)");
            function getTime() {
                var myDate = new Date();
                var myYear = myDate.getFullYear();
                var myMonth = myDate.getMonth() + 1;
                var myToday = myDate.getDate();
                var myDay = myDate.getDay();
                var myHour = myDate.getHours();
                var myMinute = myDate.getMinutes();
                var mySecond = myDate.getSeconds();
                var week = ['@Label.Sunday', '@Label.Monday', '@Label.Tuesday', '@Label.Wednesday', '@Label.Thursday', '@Label.Friday', '@Label.Saturday'];
                var nowTime;

                nowTime = myYear + '-' + fillZero(myMonth) + '-' + fillZero(myToday) + '&nbsp;&nbsp;' + fillZero(myHour) + ':' + fillZero(myMinute) + ':' + fillZero(mySecond) + '&nbsp;&nbsp;' + week[myDay] + '&nbsp;&nbsp;';
                $('#time').html(nowTime);
            };
            function fillZero(str) {
                var realNum;
                if (str < 10) {
                    realNum = '0' + str;
                } else {
                    realNum = str;
                }
                return realNum;
            }
            setInterval(getTime, 1000);
            // 设置全屏
            $('.dimension').on('click', function (e) {
                var element = document.documentElement;
                if ($(".dimension").text() == "@Html.Raw(Label.Full)") {
                    // 判断浏览器设备类型
                    if (element.requestFullscreen) {
                        element.requestFullscreen();
                    } else if (element.mozRequestFullScreen) {       //兼容火狐
                        element.mozRequestFullScreen();
                    } else if (element.webkitRequestFullscreen) {    //兼容谷歌
                        element.webkitRequestFullscreen();
                    } else if (element.msRequestFullscreen) {        //兼容IE
                        element.msRequestFullscreen();
                    }
                    $(".dimension").text("@Html.Raw(Label.Exit + Label.Full)");
                } else {
                    if (document.exitFullscreen) {
                        document.exitFullscreen();
                    } else if (document.mozCancelFullScreen) {
                        document.mozCancelFullScreen();
                    } else if (document.webkitCancelFullScreen) {
                        document.webkitCancelFullScreen();
                    } else if (document.msExitFullscreen) {
                        document.msExitFullscreen();
                    }
                    $(".dimension").text("@Html.Raw(Label.Full)");
                }
            });
            $('#btn_query').prop('disabled', true);
        });
        function getWeekNumber(date = new Date()) {
            //将周日(0)变成6，周一变成0
            const day = (date.getDay() + 6) % 7;
            const monday = new Date(date);
            monday.setDate(date.getDate() - day);
            const yearStart = new Date(date.getFullYear(), 0, 1);
            const yearStartDay = (yearStart.getDay() + 6) % 7;
            const firstMonday = new Date(yearStart);
            firstMonday.setDate(yearStart.getDate() - yearStartDay);
            const diff = monday - firstMonday;
            const week = Math.ceil(diff / (7 * 24 * 60 * 60 * 1000));
            return String(week).padStart(2, '0');
        };
        //下拉框设置
        var Datesetting = function() {
            $("#startdate, #enddate, #startyear, #startto, #endyear, #endto").css({
                "height": "0.36rem",
                "transform": "translateY(0.02rem)"
            });
            var type = $("#cmb_type").val();
            function addOptions(selectId, options, checked) {
                var $select = $(selectId);
                $select.empty();
                options.forEach(function(option) {
                    $select.append(new Option(option.label, option.value));
                });
                if(checked != null)
                {
                    $select.val(checked);
                }
            }
            if (type == "Daily") {
                $("#dateno").show();
                $("#dateto").hide();
                $('#startdate').on('change', function () {
                    var startDate = new Date($(this).val());
                    var endDate = new Date($('#enddate').val());
                    startDate.setDate(startDate.getDate() + 1);
                    var minEndDate = startDate.toISOString().split('T')[0];
                    $('#enddate').attr('min', minEndDate);
                    if (endDate < startDate) {
                        $('#enddate').val($(this).val());
                    }
                });
                $('#enddate').on('change', function () {
                    var startDate = new Date($('#startdate').val());
                    var endDate = new Date($(this).val());
                    endDate.setDate(endDate.getDate() - 1);
                    var maxStartDate = endDate.toISOString().split('T')[0];
                    $('#startdate').attr('max', maxStartDate);
                    if (startDate > endDate) {
                        $('#startdate').val($(this).val());
                    }
                });

            } else {
                $("#dateto").show();
                $("#dateno").hide();
                var currentYear = new Date().getFullYear();
                var previousYear = currentYear - 1;
                addOptions('#startyear, #endyear', [{ label: previousYear, value: previousYear },{ label: currentYear, value: currentYear }]);
                if (type == "Yearly") {
                    $("#endto, #startto").hide();
                } else {
                    $("#endto, #startto").show();
                    var checked = null;
                    var options = [];
                    if (type == "Weekly") {
                        for (var week = 1; week <= 52; week++) {
                            options.push({ label: `Week` + String(week).padStart(2, "0"), value: String(week).padStart(2, "0") });
                        }
                        checked = getWeekNumber();
                    }
                    else if (type == "Monthly") {
                        for (var month = 1; month <= 12; month++) {
                            options.push({ label: "Month" + String(month).padStart(2, "0"), value: String(month).padStart(2, "0") });
                        }
                    }
                    else if (type == "CQ") {
                        for (var quarter = 1; quarter <= 4; quarter++) {
                            options.push({ label: "CQ" + quarter, value: "CQ" + quarter });
                        }
                    }
                    else if (type == "FQ") {
                        for (var quarter = 1; quarter <= 4; quarter++) {
                            options.push({ label: "FQ" + quarter, value: "FQ" + quarter });
                        }
                    }
                    addOptions('#startto, #endto', options,checked);
                }
            }
        }
        //验证
        var startdate, enddate;
        var validate = function () {
            var type = $("#cmb_type").val();
            function validateDateRange(startdate, enddate) {
                if (startdate > enddate) {
                    alert("时间范围有误！");
                    return;
                }
            }
            if (type == "Daily") {
                startdate = $('#startdate').val();
                enddate = $('#enddate').val();
            }
            if (["Weekly", "Monthly", "CQ", "FQ"].includes(type)) {
                startdate = parseInt($("#startyear").val() + $("#startto").val());
                enddate = parseInt($("#endyear").val() + $("#endto").val());
                validateDateRange(startdate, enddate);
            }
            if (type == "Yearly") {
                startdate = parseInt($("#startyear").val());
                enddate = parseInt($("#endyear").val());
                validateDateRange(startdate, enddate);
            }

            if (["CQ", "FQ"].includes(type)) {
                startdate = `${$("#startto").val()}_${$("#startyear").val().slice(-2)}`;
                enddate = `${$("#endto").val()}_${$("#endyear").val().slice(-2)}`;
            }
            startdate = startdate.toString().replace(/-/g, '');
            enddate = enddate.toString().replace(/-/g, '');
        }
        
        $('#cmb_type').on('change', function() {
            Datesetting();
            $("#endyear").val($("#startyear option:last").val());
        });
        $('#cmb_type').val('Daily').trigger('change');
        $("#dateto select").on("change", function () {
            validate();
        });

        //ComBoxYield
        var ComboxAction = function () {
            $.post(api + "/ReportAction/GetComBoxFailureModeProduct", function(response) {
                const product = response.ReturnData.product;
                const process = response.ReturnData.process;
                $('#cmb_product_code').empty();
                product.forEach(item => {
                    $('#cmb_product_code').append(new Option(item.text, item.value));
                });

                $('#cmb_product_code').on('change', function() {
                    const selectedProduct = $(this).val();
                    const filteredProcesses = selectedProduct ? process.filter(item => item.product === selectedProduct) : [{ text: "ALL", value: "ALL" }];
                    $('#cmb_process').empty().append(new Option("ALL", "ALL"));
                    filteredProcesses.forEach(item => {
                        $('#cmb_process').append(new Option(item.text, item.value));
                    });
                });
                if (product.length > 0) {
                    $('#cmb_product_code').val(product[0].value).trigger('change');
                }
            }, "json");
        };
        
        $("#cmb_product_code,#cmb_process,#cmb_type,#dateto select,#startdate, #enddate").on("change", function () {
            getdate();
        });

        //图表自适应大小
        const chartsMap = new Map();
        const chartIds = ['etoe-chart', 'fpy-chart'];
        function echartsautomatic() {
            chartIds.forEach(chartId => {
                const el = document.getElementById(chartId);
                if (el) {
                    chartsMap.set(chartId, echarts.init(el));
                }
            });
            window.onresize = function () {
                chartsMap.forEach(function (chart) {
                    chart.resize();
                });
            };
            window.addEventListener("resize", resizeCharts);
        }
        function resizeCharts() {
            chartsMap.forEach(chart => chart.resize());
        }
        const observer = new ResizeObserver(resizeCharts);

        //定时查询
        var Tabtimer;
        function TabInterval() {
            clearInterval(Tabtimer);
            //每隔10m执行一次
            Tabtimer = setInterval(function () {
                var endDate = new Date($("#enddate").val());
                if (endDate > new Date()) {
                    getdate();
                }
            }, 10 * 60 * 1000);
        }

        $(function () {
            var startDate = new Date();
            startDate.setMonth(startDate.getMonth() - 1);
            startDate.setHours(0, 0, 0, 0);
            var endDate = new Date();
            endDate.setHours(0, 0, 0, 0);
            $('#startdate').val(startDate.toISOString().split('T')[0]);
            $('#enddate').val(endDate.toISOString().split('T')[0]);
            ComboxAction();
            // setTimeout(function () {
            //     Getdata();
            // }, 2000);
        })

        var Getdata = function () {
            getdate();
            TabInterval();
        }

        //报表导出
        var exportDdata = function(type){
            const book = XLSX.utils.book_new();
            const sheet = XLSX.utils.json_to_sheet(Tab.report);
            XLSX.utils.book_append_sheet(book, sheet);
            XLSX.writeFile(book,`${type}.xlsx`);
        }

        function loadingshow() {
            $('#btn_query').prop('disabled', true);
            $('#Tab1').css('background-image', 'url("../images/loading.gif")');
            $('#Tab1').css('background-size', '0.8rem 0.8rem');
            $('#Tab1').css('background-repeat', 'no-repeat');
            $('#Tab1').css('background-position', 'center');
        }
        function loadingnone() {
            $('#btn_query').prop('disabled', false);
            $('#Tab1').css('background-image', 'none');
        }
        function getExcelColor(percentage) {
            let red, green;
            if (percentage <= 65) {
                red = 255;
                green = Math.round((percentage / 65) * 255);
            } else if (percentage <= 90) {
                green = 255;
                red = Math.round(255 - ((percentage - 75) / 30) * 200);
            } else {
                green = Math.round(255 - ((percentage - 90) / 10) * 50);
                red = Math.round(55 - ((percentage - 90) / 10) * 25);
            }
            return `rgb(${red}, ${green}, 150)`;
        }

        //获取数据
        var Tab;
        var getdate = function () {
            validate();
            var header_key = {
                type: $("#cmb_type").val(),
                start: startdate,
                end: enddate
            };
            var pam = {};
            pam.product_code = $('#cmb_product_code').val();
            pam.process_id = $('#cmb_process').val();
            pam.header_key = JSON.stringify(header_key);
            loadingshow();
            $.ajax({
                type: "POST",
                url: api + "/ReportAction/GetYieldFailureMode",
                data: pam,
                dataType: "json",
                async: true,
                success: function (dt) {
                    loadingnone();
                    Tab = dt.ReturnData;
                    if($('#cmb_process').val() =="ALL"){
                        productChart();
                        fpyChart();
                    }else{
                        processeChart();
                        failureChart();
                    }
                    echartsautomatic();
                }
            });
        }

        function funclose() {
            $(".popup").css("display", "none");
        }

        //合并相同行
        function mergeFunc(tableId, maxCol) {
            var tab = document.getElementById(tableId);
            //var maxCol = 3;
            //maxcol用于设置需要合并的列数
            var count, start;
            for (var col = maxCol - 1; col >= 0; col--) {
                //用于存储相同个数
                count = 1;
                for (var i = 0; i < tab.rows.length; i++) {
                    if (i > 0 && col > 0 && tab.rows[i].cells[col].innerHTML == tab.rows[i - 1].cells[col].innerHTML
                        && tab.rows[i].cells[col - 1].innerHTML == tab.rows[i - 1].cells[col - 1].innerHTML) {
                        count++;
                    } else if (i > 0 && col == 0 && tab.rows[i].cells[col].innerHTML == tab.rows[i - 1].cells[col].innerHTML) {
                        count++;
                    } else {
                        if (count > 1) {
                            start = i - count;
                            tab.rows[start].cells[col].rowSpan = count;
                            for (var j = start + 1; j < i; j++) {
                                tab.rows[j].removeChild(tab.rows[j].cells[col]);
                            }
                            count = 1;
                        }
                    }
                }
                if (count > 1) {
                    start = i - count;
                    tab.rows[start].cells[col].rowSpan = count;
                    for (var j = start + 1; j < i; j++) {
                        tab.rows[j].removeChild(tab.rows[j].cells[col]);
                    }
                }
            }
        }

        //Report
        var reportDetail = function () {
            var product = $('#cmb_product_code').val();
            var process = $('#cmb_process').val();
            let filteredData = process === "ALL" && Tab.report || Tab.report.filter(item => item.STAGE === process);
            if(filteredData.length>0){
                $(".popup").css("display", "block");
                $(".popup-title").text(`${product}_${process}`);
                var data = filteredData.map(item => {
                    let newItem = Object.assign({}, item);
                    delete newItem.YEAR_NO;
                    return newItem;
                });
                $("#report").empty();
                var left_table_html = `
                <table id="myTable" class="DataSheet" border="1" style="width: 100%; height: 100%;">
                    <thead><tr></tr></thead>
                    <tbody id="yield_tbody"></tbody>
                </table>`;
                $("#report").append(left_table_html);
                var table = $('#myTable');
                var tbody = table.find('tbody');
                var headerRow = table.find('thead tr');
                var headers = Object.keys(data[0]);
                headers.forEach(function (header) {
                    headerRow.append('<th>' + header + '</th>');
                });
                data.forEach(function (row, index) {
                    index++;
                    let newRow = $(`<tr class="${(index % 2) ? "ZebraNo" : "ZebraTo"}"></tr>`);
                    headers.forEach(function (header, columnindex) {
                        if (["FAILURERATE", "FPY"].includes(header)) {
                            row[header] = (parseFloat(row[header]) * 100).toFixed(2) + '%';
                        }
                        newRow.append(`<td class="truncate">${row[header]}</td>`);
                    });
                    tbody.append(newRow);
                });
                if (data.length > 45) {
                    $("#report").css("height", "7rem");
                    $("#report").css("overflow-y", "auto");
                } else {
                    $("#report").css("height", "50%");
                }
                mergeFunc("myTable", 7);
            }
        }

        //productE2E
        var productChart = function () {
            var product = $('#cmb_product_code').val();
            var chartDom = document.getElementById('etoe-chart');
            if (chartDom) {
                echarts.dispose(chartDom);
            }
            var myChart = echarts.init(chartDom);
            var categories = Tab.input.map(item => item.DATE_TIME);
            var maxInput = Tab.input.map(item => item.MAX_INPUT);
            var minInput = Tab.input.map(item => item.MIN_INPUT);
            var etoe = Tab.input.map(item => parseFloat((item.E2E * 100).toFixed(2)));
            var option = {
                title: {
                    text: `${product} Total E2E`,
                    left: 'center',
                    textStyle: {
                        fontSize: '0.2rem',
                        fontWeight: 'bold'
                    }
                },
                tooltip: {
                    trigger: 'axis',
                    axisPointer: { type: 'cross' }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: false },
                        magicType: { show: true, type: ['line', 'bar'] },
                        restore: { show: true },
                        saveAsImage: {
                            show: true,
                            name: `${product}_Total_E2E`
                        }
                    }
                },
                legend: {
                    top: '6.5%',
                    data: ['MAX_INPUT', 'MIN_INPUT', 'E2E'],
                    textStyle: {
                        fontSize: '0.16rem',
                        fontWeight: 'bold'
                    }
                },
                grid: {
                    left: '4%',
                    right: '4%'
                },
                xAxis: {
                    type: 'category',
                    data: categories,
                    axisLabel: { rotate: 45 }
                },
                yAxis: [
                    {
                        type: 'value',
                        name: 'Input',
                        position: 'left',
                        yAxisIndex: 0,
                        splitLine: {
                            show: false
                        }
                    },
                    {
                        type: 'value',
                        name: 'E2E(%)',
                        position: 'right',
                        yAxisIndex: 1,
                        min: 0,
                        max: 100,
                        axisLabel: { formatter: '{value}%' }
                    }
                ],
                dataZoom: [
                    {
                        type: 'inside',
                        yAxisIndex: 1,
                        zoomLock: false
                    },
                    {
                        type: 'slider',
                        yAxisIndex: 1,
                        zoomLock: false,
                        right: 1,
                        width: 10
                    }
                ],
                series: [
                    {
                        name: 'MAX_INPUT',
                        type: 'bar',
                        data: maxInput,
                        barWidth: '30%'
                    },
                    {
                        name: 'MIN_INPUT',
                        type: 'bar',
                        data: minInput,
                        barWidth: '30%'
                    },
                    {
                        name: 'E2E',
                        type: 'line',
                        yAxisIndex: 1,
                        smooth: false,
                        lineStyle: {
                            width: 3,
                            color: '#FFA500'
                        },
                        itemStyle: {
                            color: '#FFA500',
                            borderWidth: 2,
                            borderColor: '#FF4500'
                        },
                        symbolSize: 8,
                        data: etoe,
                        tooltip: {
                            valueFormatter: function (value) {
                                return value.toFixed(2) + '%';
                            }
                        }
                    }
                ]
            };
            myChart.setOption(option);
        }

        //柱状堆叠图
        var processeChart = function () {
            var product = $('#cmb_product_code').val();
            var process = $('#cmb_process').val();
            var data = Tab.report;
            let stagefpyarray = [];
            let processedRecords = new Set();
            data.forEach(item => {
                let uniqueKey = `${String(item.PRODUCTTYPE).trim()}_${String(item.STAGE).trim()}_${String(item.YEAR_NO).trim()}_${String(item.DATE_TIME).trim()}`;
                if (!processedRecords.has(uniqueKey)) {
                    stagefpyarray.push({
                        PRODUCTTYPE: item.PRODUCTTYPE.trim(),
                        STAGE: item.STAGE.trim(),
                        YEAR_NO: String(item.YEAR_NO).trim(),
                        DATE_TIME: String(item.DATE_TIME).trim(),
                        FIRST_INPUT: item.FIRST_INPUT,
                        PASS_COUNT: item.PASS_COUNT,
                        FAIL: item.FAIL,
                        TOTAL_FAILURE: item.TOTAL_FAILURE,
                        FPY: item.FPY
                    });
                    processedRecords.add(uniqueKey);
                }
            });
            var chartDom = document.getElementById('etoe-chart');
            if (chartDom) {
                echarts.dispose(chartDom);
            }
            var myChart = echarts.init(chartDom);
            var categories = stagefpyarray.map(item => item.DATE_TIME);
            var firstInput = stagefpyarray.map(item => item.FIRST_INPUT);
            var totalFailure = stagefpyarray.map(item => item.TOTAL_FAILURE);
            var fpy = stagefpyarray.map(item => parseFloat((item.FPY * 100).toFixed(2)));
            var option = {
                title: {
                    text: `${product} ${process} Input Chart`,
                    left: 'center',
                    textStyle: {
                        fontSize: '0.2rem',
                        fontWeight: 'bold'
                    }
                },
                tooltip: {
                    trigger: 'axis',
                    axisPointer: { type: 'cross' }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: false },
                        magicType: { show: true, type: ['line', 'bar'] },
                        restore: { show: true },
                        saveAsImage: {
                            show: true,
                            name: `${product}_${process}_Input_Chart`
                        }
                    }
                },
                legend: {
                    top: '6.5%',
                    data: ['FIRST_INPUT', 'TOTAL_FAILURE', 'FPY'],
                    textStyle: {
                        fontSize: '0.16rem',
                        fontWeight: 'bold'
                    }
                },
                grid: {
                    left: '4%',
                    right: '4%'
                },
                xAxis: {
                    type: 'category',
                    data: categories,
                    axisLabel: { rotate: 45 }
                },
                yAxis: [
                    {
                        type: 'value',
                        name: 'Input',
                        position: 'left',
                        yAxisIndex: 0,
                        splitLine: {
                            show: false
                        }
                    },
                    {
                        type: 'value',
                        name: 'FPY(%)',
                        position: 'right',
                        yAxisIndex: 1,
                        min: 0,
                        max: 100,
                        axisLabel: { formatter: '{value}%' }
                    }
                ],
                dataZoom: [
                    {
                        type: 'inside',
                        yAxisIndex: 1,
                        zoomLock: false
                    },
                    {
                        type: 'slider',
                        yAxisIndex: 1,
                        zoomLock: false,
                        right: 1,
                        width: 10
                    }
                ],
                series: [
                    {
                        name: 'FIRST_INPUT',
                        type: 'bar',
                        data: firstInput,
                        barWidth: '30%'
                    },
                    {
                        name: 'TOTAL_FAILURE',
                        type: 'bar',
                        data: totalFailure,
                        barWidth: '30%'
                    },
                    {
                        name: 'FPY',
                        type: 'line',
                        yAxisIndex: 1,
                        smooth: false,
                        lineStyle: {
                            width: 3,
                            color: '#FFA500'
                        },
                        itemStyle: {
                            color: '#FFA500',
                            borderWidth: 2,
                            borderColor: '#FF4500'
                        },
                        symbolSize: 8,
                        data: fpy,
                        tooltip: {
                            valueFormatter: function (value) {
                                return value.toFixed(2) + '%';
                            }
                        }
                    }
                ]
            };
            myChart.setOption(option);
        }

        //FPY
        var fpyChart = function () {
            var product = $('#cmb_product_code').val();
            var data = Tab.report;
            let stagefpyarray = [];
            let processedStages = new Set();
            data.forEach(item => {
                let stageTimeKey = `${item.STAGE}_${item.DATE_TIME}`;
                if (!processedStages.has(stageTimeKey)) {
                    stagefpyarray.push({
                        PRODUCTTYPE: item.PRODUCTTYPE,
                        STAGE: item.STAGE,
                        DATE_TIME: item.DATE_TIME,
                        YEAR_NO: item.YEAR_NO,
                        FIRST_INPUT: item.FIRST_INPUT,
                        PASS_COUNT: item.PASS_COUNT,
                        FPY: item.FPY
                    });
                    processedStages.add(stageTimeKey);
                }
            });
            var chartDom = document.getElementById('fpy-chart');
            if (chartDom) {
                echarts.dispose(chartDom);
            }
            var myChart = echarts.init(chartDom);
            let stageMap = new Map();
            let xAxisSet = new Set();
            stagefpyarray.forEach(item => {
                let stage = item.STAGE;
                let year = parseInt(item.YEAR_NO, 10);
                let dateTime = item.DATE_TIME;
                let fpyValue = (parseFloat(item.FPY) * 100).toFixed(2);
                xAxisSet.add(`${year}_${dateTime}`);
                if (!stageMap.has(stage)) {
                    stageMap.set(stage, []);
                }
                stageMap.get(stage).push({ dateTime, fpyValue });
            });
            stageMap.forEach((value, key) => {
                value.sort((a, b) => a.year - b.year || a.dateTime.localeCompare(b.dateTime, undefined, { numeric: true }));
            });
            let sortedEntries = Array.from(stageMap.entries());
            sortedEntries.sort((a, b) => {
                let avgA = a[1].reduce((sum, v) => sum + parseFloat(v.fpyValue), 0) / a[1].length;
                let avgB = b[1].reduce((sum, v) => sum + parseFloat(v.fpyValue), 0) / b[1].length;
                return avgA - avgB;
            });
            let sortedFpyMap = new Map();
            for (let [key, value] of sortedEntries) {
                sortedFpyMap.set(key, value);
            }
            stageMap = sortedFpyMap;
            let xAxisData = Array.from(xAxisSet)
                .sort((a, b) => {
                    let [yearA, dateA] = a.split('_');
                    let [yearB, dateB] = b.split('_');
                    return parseInt(yearA, 10) - parseInt(yearB, 10) || dateA.localeCompare(dateB, undefined, { numeric: true });
                })
                .map(v => v.split('_')[1]);
            let seriesData = [];
            const colors = ['#ff0000', '#efdf00', '#00008b', '#6b8e23', '#008b8b', '#ff00ff', '#ff8c00', '#4682b4', '#8031a7', '#a0522d'];
            let index = 0;
            stageMap.forEach((values, stage) => {
                let dataMap = new Map(values.map(item => [item.dateTime, item.fpyValue]));
                let fpyValues = xAxisData.map(date => dataMap.get(date) || null);
                seriesData.push({
                    name: stage,
                    type: 'line',
                    data: fpyValues,
                    emphasis: {
                        focus: 'series',
                        lineStyle: {
                            opacity: 1
                        },
                        itemStyle: {
                            opacity: 1
                        }
                    },
                    label: {
                        show: false,
                        formatter: (params) => params.value !== "0.00" ? `${params.value}%` : '0.00%'
                    },
                    lineStyle: {
                        color: colors[index % colors.length],
                        width: 3
                    },
                    itemStyle: {
                        color: colors[index % colors.length],
                        borderWidth: 2
                    },
                    symbolSize: 8,
                });
                index++;
            });
            var option = {
                title: {
                    text: `${product} Yield Chart`,
                    left: 'center',
                    textStyle: {
                        fontSize: '0.2rem',
                        fontWeight: 'bold'
                    }
                },
                @*
                tooltip: {
                    trigger: 'item',
                    axisPointer: {
                        type: 'line'
                    },
                    valueFormatter: function (value) {
                        return `${value}%`;
                    }
                },
                *@
                tooltip: {
                    trigger: 'item',
                    formatter: function (params) {
                        const date = params.name;
                        const process = params.seriesName;
                        if (!date || !process) return '';
                        const marker = params.marker;
                        const filtered = Tab.report
                        .filter(d => d.DATE_TIME?.split('T')[0]?.replaceAll('-', '') === date && d.STAGE === process && d.FAILURE_COUNT > 0)
                        .sort((a, b) => b.FAILURE_COUNT - a.FAILURE_COUNT); 
                        if (filtered.length === 0) return '';
                        const summary = filtered[0];
                        let html = `<div style="padding:4px 8px;"><strong>Stage By Failure Mode (${date})</strong></div>`;
                        html += `
                            <table id="failddet" style="border-collapse: collapse; width: 100%; font-size: 12px;">
                                <tr>
                                    <th style="text-align:left;">Stage</th>
                                    <th>Input</th>
                                    <th>Output</th>
                                    <th>Fail</th>
                                    <th>PrimeYield</th>
                                </tr>
                                <tr>
                                    <td>${marker}${summary.STAGE}</td>
                                    <td>${summary.FIRST_INPUT}</td>
                                    <td>${summary.PASS_COUNT}</td>
                                    <td>${summary.TOTAL_FAILURE}</td>
                                    <td>${(summary.FPY * 100).toFixed(2)}%</td>
                                </tr>
                                <tr>
                                    <th colspan="3">FailureMode</th>
                                    <th>PrimeReject</th>
                                    <th>PrimeRejectRate</th>
                                </tr>
                        `;
                        filtered.forEach(d => {
                            html += `
                            <tr>
                                <td colspan="3">${d.FAILURE_MODE}</td>
                                <td>${d.FAILURE_COUNT}</td>
                                <td>${(d.FAILURERATE * 100).toFixed(2)}%</td>
                            </tr>`;
                        });
                        html += `</table>`;
                        return html;
                    }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: false },
                        restore: { show: true },
                        saveAsImage: {
                            show: true,
                            name: `${product}_Yield_Chart`
                        }
                    }
                },
                legend: {
                    show: true,
                    type: 'scroll',
                    width: '98%',
                    top: '6.5%',
                    data: Array.from(stageMap.keys()),
                    orient: 'horizontal',
                    itemWidth: 12,
                    itemHeight: 12,
                    scrollDataIndex: 0,
                    pageIconSize: [16, 16],
                    pageIconColor: '#0aa9cd',
                    pageTextStyle: {
                        fontSize: '0.16rem',
                    },
                    textStyle: {
                        fontSize: '0.16rem',
                        fontWeight: 'bold'
                    }
                },
                grid: {
                    left: '4%',
                    right: '3%'
                },
                xAxis: {
                    type: 'category',
                    data: xAxisData,
                    axisLabel: { rotate: 45 }
                },
                yAxis: {
                    type: 'value',
                    scale: true,
                    axisLabel: {
                        formatter: '{value}%'
                    }
                },
                series: seriesData
            };
            myChart.setOption(option);
        }

        //FAILURE
        var failureChart = function () {
            var product = $('#cmb_product_code').val();
            var process = $('#cmb_process').val();
            let filteredData = Tab.report.filter(item => item.STAGE === process);

            var chartDom = document.getElementById('fpy-chart');
            if (chartDom) {
                echarts.dispose(chartDom);
            }
            var myChart = echarts.init(chartDom);
            let failureModeMap = new Map();
            let xAxisSet = new Set();
            filteredData.forEach(item => {
                let failureMode = item.FAILURE_MODE;
                let year = parseInt(item.YEAR_NO, 10);
                let dateTime = item.DATE_TIME;
                let failRate = (parseFloat(item.FAILURERATE) * 100).toFixed(2);
                xAxisSet.add(`${year}_${dateTime}`);
                if (!failureModeMap.has(failureMode)) {
                    failureModeMap.set(failureMode, []);
                }
                failureModeMap.get(failureMode).push({ dateTime, failRate });
            });
            failureModeMap.forEach((value, key) => {
                value.sort((a, b) => a.year - b.year || a.dateTime.localeCompare(b.dateTime, undefined, { numeric: true }));
            });
            let sortedEntries = Array.from(failureModeMap.entries());
            sortedEntries.sort((a, b) => {
                let avgA = a[1].reduce((sum, v) => sum + parseFloat(v.failRate), 0) / a[1].length;
                let avgB = b[1].reduce((sum, v) => sum + parseFloat(v.failRate), 0) / b[1].length;
                return avgB - avgA;
            });
            let sortedFailureModeMap = new Map();
            for (let [key, value] of sortedEntries) {
                sortedFailureModeMap.set(key, value);
            }
            failureModeMap = sortedFailureModeMap;
            let xAxisData = Array.from(xAxisSet)
                .sort((a, b) => {
                    let [yearA, dateA] = a.split('_');
                    let [yearB, dateB] = b.split('_');
                    return parseInt(yearA, 10) - parseInt(yearB, 10) || dateA.localeCompare(dateB, undefined, { numeric: true });
                })
                .map(v => v.split('_')[1]);
            let seriesData = [];
            const colors = ['#ff0000', '#efdf00', '#00008b', '#6b8e23', '#008b8b', '#ff00ff', '#ff8c00', '#4682b4', '#8031a7', '#a0522d'];
            let index = 0;
            var generateGradientColors = (baseColor) => {
                return [
                    echarts.color.lift(baseColor, 0.4),
                    echarts.color.lift(baseColor, -0.4)
                ];
            };
            failureModeMap.forEach((values, failureMode) => {
                var colorGradient = generateGradientColors(colors[index % colors.length]);
                let dataMap = new Map(values.map(item => [item.dateTime, item.failRate]));
                let failRates = xAxisData.map(date => dataMap.get(date) || "0.00");
                seriesData.push({
                    name: failureMode,
                    type: 'line',
                    stack: 'total',
                    smooth: false,
                    showSymbol: false,
                    emphasis: { focus: 'series' },
                    lineStyle: {
                        width: 0,
                        color: colors[index % colors.length]
                    },
                    itemStyle: {
                        color: colors[index % colors.length]
                    },
                    areaStyle: {
                        opacity: 0.8,
                        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                            { offset: 0, color: colorGradient[0] },
                            { offset: 1, color: colorGradient[1] }
                        ])
                    },
                    data: failRates,
                });
                index++;
            });
            var option = {
                title: {
                    text: `${product} ${process} Failure Mode Chart`,
                    left: 'center',
                    textStyle: {
                        fontSize: '0.2rem',
                        fontWeight: 'bold'
                    }
                },
                tooltip: {
                    trigger: 'axis',
                    formatter: function (params) {
                        const date = params[0].axisValue;
                        if (!date || !process) return '';
                        const markerMap = {};
                        params.forEach(p => markerMap[p.seriesName] = p.marker);
                        const filtered = Tab.report
                        .filter(d => d.DATE_TIME?.split('T')[0]?.replaceAll('-', '') === date && d.STAGE === process && d.FAILURE_COUNT > 0)
                        .sort((a, b) => b.FAILURE_COUNT - a.FAILURE_COUNT);
                        if (filtered.length === 0) return '';
                        const summary = filtered[0];
                        let html = `<div style="padding:4px 8px;"><strong>Stage By Failure Mode (${date})</strong></div>`;
                        html += `
                            <table id="failddet" style="border-collapse: collapse; width: 100%; font-size: 12px;">
                                <tr>
                                    <th style="text-align:left;">Stage</th>
                                    <th>Input</th>
                                    <th>Output</th>
                                    <th>Fail</th>
                                    <th>PrimeYield</th>
                                </tr>
                                <tr>
                                    <td>${summary.STAGE}</td>
                                    <td>${summary.FIRST_INPUT}</td>
                                    <td>${summary.PASS_COUNT}</td>
                                    <td>${summary.TOTAL_FAILURE}</td>
                                    <td>${(summary.FPY * 100).toFixed(2)}%</td>
                                </tr>
                                <tr>
                                    <th colspan="3">FailureMode</th>
                                    <th>PrimeReject</th>
                                    <th>PrimeRejectRate</th>
                                </tr>
                        `;
                        // 子项数据行
                        filtered.forEach(d => {
                            const marker = markerMap[d.FAILURE_MODE] || '';
                            html += `
                            <tr>
                                <td colspan="3">${marker}${d.FAILURE_MODE}</td>
                                <td>${d.FAILURE_COUNT}</td>
                                <td>${(d.FAILURERATE * 100).toFixed(2)}%</td>
                            </tr>`;
                        });
                        html += `</table>`;
                        return html;
                    }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: false },
                        magicType: { show: true, type: ['bar'] },
                        restore: { show: true },
                        saveAsImage: {
                            show: true,
                            name: `${product}_${process}_Failure_Mode_Chart`
                        }
                    }
                },
                legend: {
                    show: true,
                    type: 'scroll',
                    width: '98%',
                    top: '6.5%',
                    data: Array.from(failureModeMap.keys()),
                    orient: 'horizontal',
                    itemWidth: 12,
                    itemHeight: 12,
                    scrollDataIndex: 0,
                    pageIconSize: [16, 16],
                    pageIconColor: '#0aa9cd',
                    pageTextStyle: {
                        fontSize: '0.16rem',
                    },
                    textStyle: {
                        fontSize: '0.16rem',
                        fontWeight: 'bold'
                    }
                },
                grid: {
                    left: '4%',
                    right: '3%'
                },
                xAxis: {
                    type: 'category',
                    data: xAxisData,
                    axisLabel: { rotate: 45 }
                },
                yAxis: {
                    type: 'value',
                    scale: true,
                    axisLabel: {
                        formatter: '{value}%'
                    }
                },
                series: seriesData
            };
            myChart.setOption(option);
        }

        var maximized = false;
        function toggleMaximize(elementId, maximizedId, chartId) {
            const tab = document.getElementById(elementId) || document.getElementById(maximizedId);
            if (tab) {
                if (tab.id === elementId) {
                    maximized = true;
                    tab.id = maximizedId;
                    if (chartId) maxchart(chartId);
                } else {
                    maximized = false;
                    tab.id = elementId;
                    if (chartId) minchart(chartId);
                }
            }
            observer.observe(document.getElementById("chart-container"));
        }
        function maximizedreport() {
            toggleMaximize("report_id", "maximizedreport");
        }
    </script>
</body>
</html>